package cn.zn.modules.appoin.service.impl;

import cn.hutool.core.date.CalendarUtil;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.zn.framework.common.exception.RRException;
import cn.zn.modules.appoin.dao.AppointTimeWorkMapper;
import cn.zn.modules.appoin.entity.AppoinTimeDetail;
import cn.zn.modules.appoin.entity.AppoinTimeMain;
import cn.zn.modules.appoin.entity.AppointTimeWork;
import cn.zn.modules.appoin.entity.vo.AppointTimeWorkVO;
import cn.zn.modules.appoin.service.AppoinTimeDetailService;
import cn.zn.modules.appoin.service.AppoinTimeMainService;
import cn.zn.modules.appoin.service.AppointTimeWorkService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Calendar;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class AppointTimeWorkServiceImpl extends ServiceImpl<AppointTimeWorkMapper, AppointTimeWork> implements AppointTimeWorkService {

    @Autowired
    private AppoinTimeMainService appoinTimeMainService;
    @Autowired
    private AppoinTimeDetailService appoinTimeDetailService;

    @Override
    public List<AppointTimeWorkVO> listByMain(String mainId) {
        return super.list(new QueryWrapper<AppointTimeWork>()
                .eq("APPOIN_TIME_MAIN_ID_", mainId)).stream().map(o -> {
            AppointTimeWorkVO vo = new AppointTimeWorkVO();
            BeanUtils.copyProperties(o, vo);
            return vo;
        }).collect(Collectors.toList());
    }

    @Override
    public Integer queryFreeTime(String date, String userCode, String time) {
        AppoinTimeMain appoinTimeMain = appoinTimeMainService.queryByDateAndUser(date, userCode);
        if (appoinTimeMain == null) {
            throw new RRException("未设置工作时间");
        }
        // 选择的时间、所在工作时间段的结束时间
        Calendar[] calendars = this.isAtWork(appoinTimeMain, time);
        // 是否在其他预约范围内
        if (appoinTimeDetailService.isExist(appoinTimeMain.getId(), calendars[0].getTime(), 0)) {
            throw new RRException("选择的时间已被其他人预约");
        }
        // 计算可用时间
        // 得到选择时间最近的一个预约信息
        AppoinTimeDetail appoinTimeDetail = appoinTimeDetailService.queryNearestByMainAndTime(appoinTimeMain.getId(), calendars[0].getTime());
        if (appoinTimeDetail != null) {
            return Long.valueOf(DateUtil.between(calendars[0].getTime(), appoinTimeDetail.getWorkTime(), DateUnit.MINUTE)).intValue();
        }
        return Long.valueOf(DateUtil.between(calendars[0].getTime(), calendars[1].getTime(), DateUnit.MINUTE)).intValue();
    }

    @Override
    public Calendar[] isAtWork(AppoinTimeMain appoinTimeMain, String time) {
        // 查询当天的工作时间
        List<AppointTimeWork> appointTimeWorks = super.list(new QueryWrapper<AppointTimeWork>()
                .eq("APPOIN_TIME_MAIN_ID_", appoinTimeMain.getId()));
        if (appointTimeWorks.isEmpty()) {
            throw new RRException("未设置工作时间");
        }
        // 时间处理
        String[] timeArr = time.split(":");
        if (timeArr.length != 2) {
            throw new RRException("时间格式错误");
        }
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.MILLISECOND, 0);
        calendar.setTime(appoinTimeMain.getAppoinDate());
        calendar.set(Calendar.HOUR, Integer.valueOf(timeArr[0]));
        calendar.set(Calendar.MINUTE, Integer.valueOf(timeArr[1]));
        // 得到选择的时间在哪个工作段内
        AppointTimeWork appointTimeWorkIn = null;
        // 某工作时间段的结束时间，用于计算最长时长
        Calendar end = null;
        for (AppointTimeWork appointTimeWork : appointTimeWorks) {
            String[] startTimes = appointTimeWork.getStartTime().split(":");
            String[] endTimes = appointTimeWork.getEndTime().split(":");
            Calendar start = CalendarUtil.calendar(calendar.getTime());
            start.set(Calendar.HOUR, Integer.valueOf(startTimes[0]));
            start.set(Calendar.MINUTE, Integer.valueOf(startTimes[1]));
            end = CalendarUtil.calendar(calendar.getTime());
            end.set(Calendar.HOUR, Integer.valueOf(endTimes[0]));
            end.set(Calendar.MINUTE, Integer.valueOf(endTimes[1]));
            if (DateUtil.isIn(calendar.getTime(), start.getTime(), end.getTime())) {
                appointTimeWorkIn = appointTimeWork;
                break;
            }
        }
        if (appointTimeWorkIn == null) {
            throw new RRException("选择的时间未在工作时间范围内");
        }
        Calendar[] calendars = {calendar, end};
        return calendars;
    }
}
